package com.demo.controller;

import com.google.common.io.Files;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Gauge;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.*;

@RestController
@Slf4j
public class ExporterController {

    /**
     * 测量集公共字段
     */
    private final static String LABEL_NAMES[] = {"elementType", "beginTime", "duration", "managedElement", "NRCELLID", "CELLNAME", "gNodeBID", "cellID"};

    /**
     * 所有的列
     */
    private final static String COLUMNS = "elementType|beginTime|duration|managedElement|NRCELLID|CELLNAME|gNodeBID|cellID|1911820616|1911816766|1911816767|1911816954|1911816950|1911816998|1911816999|1911820664|1911816960|1911816961|1911816962|1911816963|1911827150|1911817080|1911817035|1911817071|1911817070|1911816994|1911816993|1911816967|1911816966|1911816968|1911816969|1911816987|1911816991|1911816989|1911816986|1911820464|1911820463|1911817056|1911817069|1911817063|1911817066|1911820460|1911817044|1911820684|1911817084|1911820677|1911820679|1911816730|1911816733|1911816728|1911820478|1911816732|1911816731|1911816771|1911816772|1911816972|1911820473|1911820517|1911820516|1911816773|1911816777|1911816778|1911817854|1911817855|1911816746|1911820721|1911816752|1911817841|1911820723|1911817843|1911816843|1911816753|1911816748|1911820730|1911817853|1911817852|1911816738|1911816737|1911816747|1911816756|1911816757|1911816907|1911816908|1911816909|1911816910|1911816912|1911816921|1911817092|1911817093|1911819864|1911819865|1911819866|1911819874|1911819875|1911819876|1911820624|1911827191|1911827192";

    /**
     * 测试使用NRCELL测量集
     */
    private final static String NRCELL = "NRCELL";

    /**
     * 所有列的list
     */
    private final static List<String> COLUMNS_LIST;

    /**
     * 存放每一个counter的集合
     */
    private Map<String, Gauge> counterMap = new HashMap<>();

    /**
     * 存放处理过的文件集合
     */
    Set<String> parseFiles = Collections.synchronizedSet(new HashSet<>());

    /**
     * 注册到Collector上
     */
    @Autowired
    CollectorRegistry collectorRegistry;

    @Value("${filefrom}")
    String filefrom;

    @Value("${fileto}")
    String fileto;

    @Value("${batch_insert}")
    int BATCH_INSERT;

    static {
        COLUMNS_LIST = Arrays.asList(COLUMNS.split("\\|"));
    }

    @PostConstruct
    public void init() {
        // 遍历所有的列然后把非常用字段加进counterMap中
        COLUMNS_LIST.forEach(item -> {
            // 如果不是常用字段就加进counterMap中
            if (!Arrays.stream(LABEL_NAMES).anyMatch(it -> item.equals(it))) {
                setCounter(item);
            }
        });
    }

    /**
     * 数据入库
     *
     * @return
     * @throws Exception
     */
    @RequestMapping("/insertData")
    public String insertData() {
        File handleDir = new File(fileto);
        if (!handleDir.exists()) {
            handleDir.mkdirs();
        }
        File fileDir = new File(filefrom);
        if (fileDir.isDirectory()) {
            File[] files = fileDir.listFiles();
            if (files != null && files.length > 0) {
                for (int i = 0, j = 0; i < files.length && j < BATCH_INSERT; i++) {
                    File file = files[i];
                    if (!file.isDirectory()) {
                        String fileName = file.getName();
                        if (parseFiles.contains(fileName)) {
                            continue;
                        } else {
                            parseFiles.add(fileName);
                            String fileType = fileName.split("_")[0];
                            if (NRCELL.equals(fileType)) {
                                j++;
                                getMetrics(file);
                            }
                            moveFile(file);
                        }
                    }
                }
            }
        }
        return "数据插入成功";
    }


    /**
     * 将每一个counter注册到collectorRegistry
     * 并且将counter的key存储到map中
     *
     * @param counter
     */
    private void setCounter(String counter) {
        if (counter != null && !"".equals(counter)) {
            String counterName = getCounterKey(counter);
            Gauge guage = Gauge.build()
                    .name(counterName)
                    .labelNames(LABEL_NAMES)
                    .help(NRCELL.concat("的counter: ").concat(counter)).register(collectorRegistry);
            counterMap.put(counterName, guage);
        }
    }

    /**
     * 获取metrics
     *
     * @param file
     */
    private void getMetrics(File file) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
            //跳过第一行
            bufferedReader.readLine();
            String line;
            int columnSize = COLUMNS_LIST.size();
            while ((line = bufferedReader.readLine()) != null) {
                String[] vals = line.split("\\|", -1);
                if (columnSize == vals.length) {
                    List<String> labelList = new ArrayList<>();
                    labelList.clear();
                    // 将lable和值放到gauge
                    for (int i = 0, len = columnSize; i < len; i++) {
                        //如果是前8个值则放到lable中
                        if (i < LABEL_NAMES.length) {
                            labelList.add(vals[i]);
                            continue;
                        }
                        // 从map中获取到这个counter的gauge
                        Gauge gauge = counterMap.get(getCounterKey(COLUMNS_LIST.get(i)));
                        gauge.labels(labelList.toArray(new String[labelList.size()])).set(transStrToDouble(vals[i]));
                    }
                } else {
                    log.info(line);
                    log.info(file.getName());
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 拼接counter的关键字
     *
     * @param counter
     * @return
     */
    private String getCounterKey(String counter) {
        return NRCELL.concat("_").concat(counter);
    }

    /**
     * 将文件移动到处理后的目录
     *
     * @param file
     */
    private void moveFile(File file) {
        File desFile = new File(fileto.concat(File.separator).concat(file.getName()));
        if (!desFile.exists()) {
            try {
                desFile.createNewFile();
                Files.move(file, desFile);
                log.info("处理完毕，移除文件：{}", file.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 将值转换成为Prometheus需要的值
     *
     * @param str
     * @return
     */
    private Double transStrToDouble(String str) {
        Double result = Double.valueOf("0.0");
        if (str == null || "".equals(str) || "NIL".equals(str)) {
            return result;
        }
        // 如果转换异常则使用默认值
        try {
            result = Double.parseDouble(str);
        } catch (Exception e) {

        }
        return result;
    }

}
